package com.proton.carepatchtemp.activity;

import android.animation.Animator;
import android.graphics.Color;
import android.graphics.DashPathEffect;
import android.graphics.RectF;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.os.SystemClock;
import android.support.design.widget.NavigationView;
import android.support.v4.content.ContextCompat;
import android.text.TextUtils;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;

import com.github.mikephil.charting.charts.LineChart;
import com.github.mikephil.charting.components.Description;
import com.github.mikephil.charting.components.Legend;
import com.github.mikephil.charting.components.LimitLine;
import com.github.mikephil.charting.components.XAxis;
import com.github.mikephil.charting.components.YAxis;
import com.github.mikephil.charting.data.BarEntry;
import com.github.mikephil.charting.data.Entry;
import com.github.mikephil.charting.data.LineData;
import com.github.mikephil.charting.data.LineDataSet;
import com.github.mikephil.charting.formatter.IAxisValueFormatter;
import com.github.mikephil.charting.highlight.Highlight;
import com.github.mikephil.charting.listener.OnChartValueSelectedListener;
import com.proton.carepatchtemp.BuildConfig;
import com.proton.carepatchtemp.R;
import com.proton.carepatchtemp.application.VCare;
import com.proton.carepatchtemp.base.BaseActivity;
import com.proton.carepatchtemp.constant.Codes;
import com.proton.carepatchtemp.constant.Config;
import com.proton.carepatchtemp.constant.Extras;
import com.proton.carepatchtemp.constant.Settings;
import com.proton.carepatchtemp.database.TestManager;
import com.proton.carepatchtemp.ui.ChartView.DayAxisValueFormatter;
import com.proton.carepatchtemp.ui.ChartView.MyAxisValueFormatter;
import com.proton.carepatchtemp.ui.ChartView.XYMarkerView;
import com.proton.carepatchtemp.utils.FormatUtils;
import com.proton.carepatchtemp.utils.NumUtils;
import com.proton.carepatchtemp.utils.SpUtils;
import com.proton.carepatchtemp.utils.TastyUtils;
import com.proton.carepatchtemp.utils.UiUtils;
import com.proton.carepatchtemp.utils.eventbus.MainEvent;
import com.proton.carepatchtemp.utils.ui.ToastUtils;
import com.sdsmdg.tastytoast.TastyToast;

import java.lang.ref.WeakReference;
import java.text.SimpleDateFormat;
import java.util.ArrayList;

public class RealTimeChartActivity extends BaseActivity
        implements NavigationView.OnNavigationItemSelectedListener, OnChartValueSelectedListener {

    //  本地缓存数据是否读取完毕
    public boolean isLoaded = false;
    protected RectF mOnValueSelectedRectF = new RectF();
    boolean moveFlag = true;
    private Long reportId;
    //    private String macAddress;
//    private ArrayList<Integer> mColors;
    private ArrayList<Entry> mYVals2;
    private ArrayList<Entry> mYVals1;
    private float maxTemp = 0F;
    private Float minTemp;
    private long timeSum = 0;
    private long lowTime = 0;
    private long highTime = 0;
    private Long startTime;
    private String mac = "";
    private float warningHigh = 37.5f;
    private float warningLow = 35.0f;
    private MyHandler mHandler;
    private DayAxisValueFormatter mXAxisFormatter;
    private ImageButton mBtnBack;
    private LineChart mBcRealtimeChart;
    /**
     * --分--秒
     */
    private TextView mTvAllTestTime;
    private ImageView mIvHighestTemp;
    private TextView mTvHighOrLow;
    /**
     * --.--
     */
    private TextView mTvMaxTemp;
    /**
     * ℃
     */
    private TextView mTvRealNameUnit;
    private LinearLayout mLnlTempFlag;
    private LinearLayout mContentRealTimeChart;

    @Override
    public void dealEvent(MainEvent event) {
        switch (event.getId()) {
            case Codes.REPORT_REAL_TIME_DRAW:
                if (isLoaded) {

                    //预测值
                    float val = Float.parseFloat(event.getRet());
                    //真实值
                    float val2 = Float.parseFloat(event.getMsg());
                    //过高时间
                    if (NumUtils.withinTempRange(val) && val > warningHigh) {
                        highTime += Settings.TEMP_LOAD_TIME_DIV;
                    }

                    //过低时间
                    if (NumUtils.withinTempRange(val) && val < warningLow) {
                        lowTime += Settings.TEMP_LOAD_TIME_DIV;
                    }

                    if (1 == SpUtils.getInt(Extras.TEMP_UNIT, Config.TEMP_UNIT_DEFAULT)) {
                        mYVals1.add(new Entry(mYVals1.size() + 1, val));
                        mYVals2.add(new Entry(mYVals2.size() + 1, val2));
                    } else {
                        mYVals1.add(new Entry(mYVals1.size() + 1, FormatUtils.c2F(val)));
                        mYVals2.add(new Entry(mYVals2.size() + 1, FormatUtils.c2F(val2)));
                    }

                    timeSum += Settings.TEMP_LOAD_TIME_DIV;

                    addData();
                    updataUI();
                }
                break;
            default:
                break;
        }
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.content_real_time_chart);
        mHandler = new MyHandler(RealTimeChartActivity.this);
        mac = getIntent().getExtras().getString(Extras.DEVICE_MAC);
        if (TextUtils.isEmpty(mac)) {
            TastyUtils.makeTextShort(R.string.string_get_device_info_fail, TastyToast.WARNING);
            finish();
        }

        if (null == TestManager.getAllTemps(mac) || TestManager.getAllTemps(mac).size() <= 0) {
            ToastUtils.s(R.string.string_wait_no_data);
            finish();
            return;
        }

        startTime = TestManager.getStartTime(mac);
        reportId = TestManager.getReportID(mac);
        if (null == startTime) {
            startTime = System.currentTimeMillis();
        }
        timeSum = System.currentTimeMillis() - startTime;
        SystemClock.currentThreadTimeMillis();
        initView();
        initChart();
//        LogUtils.e(reportId);
        setData(mBcRealtimeChart);


        warningHigh = SpUtils.getFloat(Extras.WARNING_HIGHEST_TEMP, 37.5f);
        warningLow = SpUtils.getFloat(Extras.WARNING_LOWEST_TEMP, 35.0f);

        if (1 == SpUtils.getInt(Extras.TEMP_UNIT, Config.TEMP_UNIT_DEFAULT)) {
            mTvRealNameUnit.setText(" ℃");
        } else {
            mTvRealNameUnit.setText(" ℉");
        }
        //设置监听器
        setListener();
    }

    private void initChart() {
        mBcRealtimeChart.setOnChartValueSelectedListener(this);

        mBcRealtimeChart.getDescription().setEnabled(false);

//        mBcRealtimeChart.setDrawBarShadow(false);

        // if more than 60 entries are displayed in the chart, no values will be
        // drawn
//        mBcReportChart.setMaxVisibleValueCount(60);

        // scaling can now only be done on x- and y-axis separately
        mBcRealtimeChart.setPinchZoom(true);

        mBcRealtimeChart.setScaleYEnabled(false);

        mBcRealtimeChart.setScaleXEnabled(true);

        mBcRealtimeChart.setDrawGridBackground(true);

        mBcRealtimeChart.setDoubleTapToZoomEnabled(false);

        if (1 == SpUtils.getInt(Extras.TEMP_UNIT, Config.TEMP_UNIT_DEFAULT)) {
            mBcRealtimeChart.setVisibleYRange(30F, 42F, YAxis.AxisDependency.LEFT);
        } else {
            mBcRealtimeChart.setVisibleYRange(86F, 107.6F, YAxis.AxisDependency.LEFT);
        }
        //  边界是否绘制
        mBcRealtimeChart.setDrawBorders(true);

        mBcRealtimeChart.setNoDataText(getString(R.string.have_no_data));

        mBcRealtimeChart.setDrawMarkers(true);

        mBcRealtimeChart.animateX(1000);

        mXAxisFormatter = new DayAxisValueFormatter(mBcRealtimeChart);
        mXAxisFormatter.setStartTime(startTime);

        long time = startTime + TestManager.get(mac).firstHistory.size() * Settings.TEMP_LOAD_TIME_DIV;
        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//初始化Formatter的转换格式。

        LimitLine cacheLine = new LimitLine(TestManager.get(mac).firstHistory.size(), getString(R.string.string_connect_time) + "\n" + formatter.format(time).split(" ")[1]);
        cacheLine.setLabelPosition(LimitLine.LimitLabelPosition.RIGHT_BOTTOM);
        cacheLine.setTextSize(10f);
        cacheLine.setLineWidth(1f);
        cacheLine.enableDashedLine(10f, 10f, 0f);
        cacheLine.setTextColor(ContextCompat.getColor(this, R.color.gray));
        cacheLine.setLineColor(ContextCompat.getColor(this, R.color.blueDeep));


        XAxis xAxis = mBcRealtimeChart.getXAxis();
        xAxis.setPosition(XAxis.XAxisPosition.BOTTOM);
        xAxis.enableGridDashedLine(10f, 10f, 0f);
        xAxis.setValueFormatter(mXAxisFormatter);
        xAxis.addLimitLine(cacheLine);
//        xAxis.setDrawGridLines(true);

        float high = SpUtils.getFloat(Extras.WARNING_HIGHEST_TEMP, 37.0F);
        float low = SpUtils.getFloat(Extras.WARNING_LOWEST_TEMP, 35.0F);

        LimitLine limitLine;
        if (1 == SpUtils.getInt(Extras.TEMP_UNIT, Config.TEMP_UNIT_DEFAULT)) {
            limitLine = new LimitLine(high, high + "℃");
        } else {
            limitLine = new LimitLine(FormatUtils.c2F(high), FormatUtils.c2F(high) + "℉");
        }
        limitLine.setTextSize(10f);
        limitLine.setLineWidth(2f);
        limitLine.enableDashedLine(10f, 10f, 0f);
        limitLine.setTextColor(ContextCompat.getColor(this, R.color.orange));
        limitLine.setLineColor(ContextCompat.getColor(this, R.color.orange));

        LimitLine lowLimitLine;
        if (1 == SpUtils.getInt(Extras.TEMP_UNIT, Config.TEMP_UNIT_DEFAULT)) {
            lowLimitLine = new LimitLine(low, low + "℃");
        } else {
            lowLimitLine = new LimitLine(FormatUtils.c2F(low), FormatUtils.c2F(low) + "℉");
        }
        lowLimitLine.setTextSize(10f);
        lowLimitLine.setLineWidth(2f);
        lowLimitLine.enableDashedLine(10f, 10f, 0f);
        lowLimitLine.setTextColor(Color.BLACK);
        lowLimitLine.setLineColor(Color.BLACK);

        IAxisValueFormatter custom = new MyAxisValueFormatter();

        YAxis leftAxis = mBcRealtimeChart.getAxisLeft();
        leftAxis.enableGridDashedLine(10f, 10f, 0f);

        if (1 == SpUtils.getInt(Extras.TEMP_UNIT, Config.TEMP_UNIT_DEFAULT)) {
            leftAxis.setAxisMinimum(30F);
            leftAxis.setAxisMaximum(42F);
        } else {
            leftAxis.setAxisMinimum(86F);
            leftAxis.setAxisMaximum(107.6F);
        }

//        leftAxis.setDrawGridLines(true);
        leftAxis.addLimitLine(limitLine);
        leftAxis.addLimitLine(lowLimitLine);

        //  隐藏左侧y轴网格线
//        leftAxis.setDrawGridLines(false);
//        leftAxis.setTypeface(mTfLight);
        leftAxis.setLabelCount(8, false);
        leftAxis.setValueFormatter(custom);
        leftAxis.setPosition(YAxis.YAxisLabelPosition.OUTSIDE_CHART);
        leftAxis.setSpaceTop(15f);

        YAxis rightAxis = mBcRealtimeChart.getAxisRight();
        rightAxis.setEnabled(false);

        Legend l = mBcRealtimeChart.getLegend();
        l.setEnabled(false);

    }

    private void setData(LineChart mBcReportChart) {
        isLoaded = false;

        //预测值
        mYVals1 = new ArrayList<>();
        mYVals1.clear();
        //真实值
        mYVals2 = new ArrayList<>();
        mYVals2.clear();

        minTemp = TestManager.getLowestTemp(mac);
        maxTemp = TestManager.getHighestTemp(mac);

        for (int i = 1; i < TestManager.get(mac).afterDealTemps.size(); i++) {

            float val = TestManager.get(mac).afterDealTemps.get(i - 1);
            float val2 = TestManager.get(mac).allTemps.get(i - 1);
            //过高时间
            if (NumUtils.withinTempRange(val) && val > warningHigh) {
                highTime += Settings.TEMP_LOAD_TIME_DIV;
            }

            //过低时间
            if (NumUtils.withinTempRange(val) && val < warningLow) {
                lowTime += Settings.TEMP_LOAD_TIME_DIV;
            }

            if (1 == SpUtils.getInt(Extras.TEMP_UNIT, Config.TEMP_UNIT_DEFAULT)) {
                mYVals1.add(new BarEntry(i, val));
                mYVals2.add(new BarEntry(i, val2));
            } else {
                mYVals1.add(new BarEntry(i, FormatUtils.c2F(val)));
                mYVals2.add(new BarEntry(i, FormatUtils.c2F(val2)));
            }
        }

        //预测曲线
        LineDataSet set1;

        set1 = new LineDataSet(mYVals1, "Data set1");
        set1.setDrawFilled(true);
        set1.setDrawCircles(false);
        set1.disableDashedLine();
        set1.enableDashedHighlightLine(10f, 5f, 0f);
        set1.setColor(Color.TRANSPARENT);
        set1.setCircleColor(Color.BLACK);
        set1.setLineWidth(0f);
        set1.setCircleRadius(3f);
        set1.setDrawCircleHole(false);
        set1.setDrawValues(false);
        set1.setDrawFilled(true);
        set1.setFormLineWidth(1f);
        set1.setFormLineDashEffect(new DashPathEffect(new float[]{10f, 5f}, 0f));
        set1.setFormSize(15.f);

        Drawable drawable = ContextCompat.getDrawable(this, R.drawable.line_chart);
        drawable.setAlpha(Config.CHART_ALPHA);
        set1.setFillDrawable(drawable);


        //实时曲线
        LineDataSet set2;

        set2 = new LineDataSet(mYVals2, "Data set2");
        set2.setDrawFilled(true);
        set2.setDrawCircles(false);
        set2.disableDashedLine();
        set2.enableDashedHighlightLine(10f, 5f, 0f);
        set2.setColor(Color.GREEN);
        set2.setCircleColor(Color.BLACK);
        set2.setLineWidth(0f);
        set2.setCircleRadius(3f);
        set2.setDrawCircleHole(false);
        set2.setDrawValues(false);
        set2.setDrawFilled(false);
        set2.setFormLineWidth(1f);
        set2.setFormLineDashEffect(new DashPathEffect(new float[]{10f, 5f}, 0f));
        set2.setFormSize(15.f);

        LineData data;

        if (BuildConfig.LOG_DEBUG) {
            data = new LineData(set1, set2);
        } else {
            data = new LineData(set1);
        }

        mBcReportChart.setData(data);

        XYMarkerView mv = new XYMarkerView(this, mXAxisFormatter);
        mv.setStartTime(startTime);
        mv.setChartView(mBcRealtimeChart); // For bounds control
        mBcRealtimeChart.setMarker(mv); // Set the marker to the chart

        if (maxTemp < 30) {
            Description description = new Description();
            description.setText(getString(R.string.string_out_of_range_temp));
            mBcReportChart.setDescription(description);
        }

        if (null != mYVals2) {
//                timeSum = mYVals2.size() * 8000L;
        }

        mBcReportChart.invalidate();
        updataUI();

        isLoaded = true;

//        mYVals2.addAll(mYVals1);

    }

    private void addData() {
        LineDataSet set1;
        LineDataSet set2;
        if (mBcRealtimeChart.getData() != null &&
                mBcRealtimeChart.getData().getDataSetCount() > 0) {
            set1 = (LineDataSet) mBcRealtimeChart.getData().getDataSetByLabel("Data set1", true);
            set1.setValues(mYVals1);

            if (BuildConfig.LOG_DEBUG) {
                set2 = (LineDataSet) mBcRealtimeChart.getData().getDataSetByLabel("Data set2", true);
                set2.setValues(mYVals2);
            }

            if (maxTemp < 30) {
                Description description = new Description();
                description.setText(getString(R.string.string_out_of_range_temp));
                mBcRealtimeChart.setDescription(description);
            } else {
                mBcRealtimeChart.setDescription(null);
            }
            mBcRealtimeChart.getData().notifyDataChanged();
            mBcRealtimeChart.notifyDataSetChanged();
            mBcRealtimeChart.invalidate();
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        TestManager.setDrawRealLine(mac, false);
        mHandler.removeCallbacksAndMessages(null);
        if (mBcRealtimeChart != null) {
            mBcRealtimeChart.clear();
        }
    }

    @Override
    public void setListener() {
        mBtnBack.setOnClickListener(view -> {
            finish();
        });


        mLnlTempFlag.setOnClickListener(v -> {
            if (moveFlag) {
                mLnlTempFlag.animate()
                        .translationYBy(-(mLnlTempFlag.getHeight() - UiUtils.dip2px(RealTimeChartActivity.this, 16)))
                        .setDuration(200).start();
                moveFlag = false;
            } else {
                mLnlTempFlag.animate()
                        .translationYBy(mLnlTempFlag.getHeight() - UiUtils.dip2px(RealTimeChartActivity.this, 16))
                        .setDuration(200).start();
                moveFlag = true;
            }
        });
        mLnlTempFlag.animate().setListener(new Animator.AnimatorListener() {
            @Override
            public void onAnimationStart(Animator animation) {
                mLnlTempFlag.setClickable(false);
            }

            @Override
            public void onAnimationEnd(Animator animation) {
                mLnlTempFlag.setClickable(true);
            }

            @Override
            public void onAnimationCancel(Animator animation) {

            }

            @Override
            public void onAnimationRepeat(Animator animation) {

            }
        });
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
//        getMenuInflater().inflate(R.menu.real_time_chart, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
//        int id = item.getItemId();
//
//        //noinspection SimplifiableIfStatement
//        if (id == R.id.action_settings) {
//            return true;
//        }

        return super.onOptionsItemSelected(item);
    }

    @SuppressWarnings("StatementWithEmptyBody")
    @Override
    public boolean onNavigationItemSelected(MenuItem item) {
        // Handle navigation view item clicks here.
        return true;
    }

    private void initView() {

        mBtnBack = findViewById(R.id.btn_back);
        mBcRealtimeChart = findViewById(R.id.bc_realtime_chart);
        mTvAllTestTime = findViewById(R.id.tv_all_test_time);
        mIvHighestTemp = findViewById(R.id.iv_highest_temp);
        mTvHighOrLow = findViewById(R.id.tv_high_or_low);
        mTvMaxTemp = findViewById(R.id.tv_max_temp);
        mTvRealNameUnit = findViewById(R.id.tv_real_name_unit);
        mLnlTempFlag = findViewById(R.id.lnl_temp_flag);
        mContentRealTimeChart = findViewById(R.id.content_real_time_chart);
    }

    private void updataUI() {
        mTvAllTestTime.setText(FormatUtils.formatTime(timeSum));

        minTemp = TestManager.getLowestTemp(mac);
        maxTemp = TestManager.getHighestTemp(mac);

        if (maxTemp > SpUtils.getFloat(Extras.WARNING_HIGHEST_TEMP, 37.5f)) {
            mTvMaxTemp.setTextColor(ContextCompat.getColor(VCare.get(), R.color.orange));
            mIvHighestTemp.setImageResource(R.mipmap.realtime_high_temp_icon);
            mLnlTempFlag.setBackground(ContextCompat.getDrawable(this, R.drawable.red_radius_null_bg));
        }

        if (NumUtils.withinTempRange(maxTemp)) {

            if (1 == SpUtils.getInt(Extras.TEMP_UNIT, Config.TEMP_UNIT_DEFAULT)) {
                mTvMaxTemp.setText(maxTemp + "");

            } else {
                mTvMaxTemp.setText(FormatUtils.c2F(maxTemp) + "");
            }

        } else if (25F > maxTemp) {

            if (1 == SpUtils.getInt(Extras.TEMP_UNIT, Config.TEMP_UNIT_DEFAULT)) {
                mTvMaxTemp.setText("< 25.00");

            } else {
                mTvMaxTemp.setText("< 77.00");

            }

        } else if (45F < maxTemp) {

            if (1 == SpUtils.getInt(Extras.TEMP_UNIT, Config.TEMP_UNIT_DEFAULT)) {
                mTvMaxTemp.setText("> 45.00");

            } else {
                mTvMaxTemp.setText("> 113.00");

            }

        }
    }

    @Override
    public void onEventMainThread(MainEvent event) {
        dealOnEvent(event);
    }

    @Override
    public void onValueSelected(Entry e, Highlight h) {

//        if (e == null)
//            return;
//
//        RectF bounds = mOnValueSelectedRectF;
//        mBcRealtimeChart.getBarBounds((BarEntry) e, bounds);
//        MPPointF position = mBcRealtimeChart.getPosition(e, YAxis.AxisDependency.LEFT);
//
//        Log.i("bounds", bounds.toString());
//        Log.i("position", position.toString());
//
//        LogUtils.i("x-index",
//                "low: " + mBcRealtimeChart.getLowestVisibleX() + ", high: "
//                        + mBcRealtimeChart.getHighestVisibleX());
//
//        MPPointF.recycleInstance(position);
    }

    @Override
    public void onNothingSelected() {

    }

    private static class MyHandler extends Handler {
        private WeakReference<RealTimeChartActivity> activityWeakReference;

        public MyHandler(RealTimeChartActivity activity) {
            activityWeakReference = new WeakReference<>(activity);
        }

        @Override
        public void handleMessage(Message msg) {
            RealTimeChartActivity activity = activityWeakReference.get();
            if (activity != null) {

            }
        }
    }

}
